package com.fwj.utils;

import com.fwj.SynMain;
import com.fwj.config.Constants;
import com.fwj.exception.EsbSynException;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.log4j.Logger;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

public class FormatUtil {

    private static Logger logger = Logger.getLogger(FormatUtil.class);
    public static String nl_windows = "\r\n";//windows 换行符
    private static String nl_linux = "\n";//linux 换行符


    public static Map<String, List> esbVerify(String[] datas)  {
        Map<String, List> serviceCodeIPMap = new HashMap<String, List>();
        String returnMessage = "";
        try {
            if(datas==null||datas.length==0)
                throw new EsbSynException("读取的配置文件为空.");

            for (int i = 0; i < datas.length; i++) {

                String servicecode = datas[i].split(",")[0];
                String ips = datas[i].split(",")[1];
                List ipList = new ArrayList();
                String ipsstr[] = ips.split("\\|");
                for (int j = 0; j < ipsstr.length; j++) {
                    //如果查找到以10.128.开头的ip,则不添加.
                    if (ipsstr[j].startsWith("10.128.", 0)) {
                        returnMessage += "第" + (i + 1) + "行IP格式出错！出现10.128开头\n  ";
                        continue;
                    }
                    //如果发现重复,则不添加,输出提示.
                    if (!ipList.contains(ipsstr[j])) {
                        ipList.add(ipsstr[j]);
                    } else {
                        returnMessage += "ip+port有重复!" + ipsstr[j]+"\n ";
                    }
                }
                //servicecode临时集合.如果发现servicecode已经存在,则不添加.
                if (serviceCodeIPMap.containsKey(servicecode)) {
                    returnMessage += "serviceCode有重复!已经用最新的覆盖!! " + servicecode+"\n  ";

                }
                serviceCodeIPMap.put(servicecode, ipList);

            }
            if (!"".equals(returnMessage))
                logger.error(returnMessage);

        } catch (ArrayIndexOutOfBoundsException e) {
            logger.error("截取字符出错！数据同步文件" + Constants.syn_datafile + "格式不正确！" + e.getMessage());

            throw new EsbSynException(e);

        }
        return serviceCodeIPMap;
    }




    /**
     * 查询F5配置中的Pools数量，并封装为List
     *
     * @return
     * @author fwj
     * @date 2015年12月6日12:28:14
     */
    public static List<Map<String, List>> formatPools(String fileContent)  {

        fileContent = fileContent.replaceAll(" ", "");

        String[] files = fileContent.split("ltmpool/Common/");

        List<Map<String, List>> list = new ArrayList<Map<String, List>>();
        for (int i = 1; i < files.length; i++) {
            if (i == files.length - 1) {
                files[i] = files[i].split("ltm")[0];
            }
            String pool = files[i].split("\\{")[0];

            String[] ips = files[i].split("Common/");

            List ipList = new ArrayList();
            for (int j = 1; j < ips.length - 1; j++) {
                String ip = ips[j].split("\\{")[0];
                ipList.add(ip);
            }

            Map map = new HashMap();
            map.put("pool", pool);
            map.put("ip", ipList);//包含IP的整段字符串
            list.add(map);

        }

        return list;
    }
    /**
     * 第一步, 获取文件，检测文件格式和数据格式合法性
     *
     * @author fwj
     * @date 2015年12月6日12:03:43
     */
    public static String getDuubToF5Data() {

        File file = new File(Constants.syn_datafile);
        File[] files = file.listFiles();
        List fileList = Arrays.asList(files);
        List newList = null;
        String fileContent = "";
        try {
            // 对文件进行排序.
            newList = EsbsynUtil.getFileSort(fileList, Constants.syn_datafile);
            boolean boo = false;
            for (int i = 0; i < newList.size(); i++) {
                File nfile = (File) newList.get(i);
                //找到文件名为Dubbo_to_F5开头的文件 bat结尾的文件. 合并到string.
                String fileName = nfile.getName();
                if (nfile.isFile() && fileName.startsWith("Dubbo_to_F5") && fileName.endsWith(".dat")) {
                    SynMain.data_toF5Name.add(Constants.syn_datafile + fileName);
                    //Dubbo_to_F5_20151203_01.dat
                    if (fileContent.indexOf(nl_windows) > -1) {
                        fileContent += EsbsynUtil.readToString(Constants.syn_datafile + fileName).trim().replaceAll("", "") + nl_windows;
                    } else {
                        fileContent += EsbsynUtil.readToString(Constants.syn_datafile + fileName).trim().replaceAll("", "") + nl_linux;

                    }
                    boo = true;

                }
            }
            if (!boo) {
                String msg = Constants.syn_datafile + "路径下找不到Dubbo_to_F5数据文件!";
                logger.error(msg);

                throw new EsbSynException(msg);

            }
        }  catch (IOException e) {
            logger.error(e.getMessage());
            e.printStackTrace();

        }
        return fileContent;
    }
    /**
     * 格式化数据同步文件Dubbo_to_F5_XXXXXXX_01.dat，封装为LIST(需检验合法性)
     * List<Map<[servicecode], List[ipList]>>
     *
     * @return
     * @author fwj
     * @date 2015年12月6日12:28:14
     */
    public static List<Map<String, List>> formatSynDataFile() {
        String synfile = getDuubToF5Data();
        String[] datas = null;
        if (synfile.indexOf(nl_windows) > -1) {
            datas = synfile.split(nl_windows);//windows中换行符
        } else {
            datas = synfile.split(nl_linux);
        }
        //检验合法性
        logger.info("正在检验" + Constants.syn_datafile + "文件合法性...校验前一共" + datas.length + "条数据");
        EsbsynUtil.ipCheck(datas);
        Map<String, List> serviceCodeIPMap = FormatUtil.esbVerify(datas);
        List<Map<String, List>> list = EsbsynUtil.mapToList(serviceCodeIPMap);
        logger.info("校验后一共" + list.size() + "条数据");

        if (!SynMain.dubbo_status)
          writeDubboFile(list);

        //文件备份
        return list;
    }


    private static void writeDubboFile(List<Map<String, List>> list) {

        Date date = new Date();
        SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");

        String newFilename = "Dubbo_to_F5_" + sf.format(date) + "_ALL.txt";
        String filePath = Constants.syn_datafile +newFilename;
        File file  = new File(filePath);
        FileOutputStream fos =null;
        try {
            file.createNewFile();
            byte[] bytes = new byte[512];
            StringBuilder rows = new StringBuilder();
            for (int i=0;i<list.size();i++){
                Map map = (HashMap) list.get(i);
                String servicecode = (String) map.get("servicecode");
                List ipList = (ArrayList) map.get("ipList");
                StringBuilder ipStr = new StringBuilder();
                if (ipList.size()>0){
                    for (int j=0;j<ipList.size();j++){
                        String ip =(String)ipList.get(j);
                        String split = j==ipList.size()-1?"":"|";
                        ipStr.append(ip+split);
                    }
                }
                rows.append(servicecode).append(",").append(ipStr).append(nl_linux);
            }
            fos = new FileOutputStream(file);
            bytes = rows.toString().getBytes();
            fos.write(bytes,0,rows.toString().length());
            //完成后会迁移.
            SynMain.data_toF5Name.add(filePath);
            logger.info("已生成汇总文件：" + filePath);
            SynMain.dubbo_status=true;
        } catch (IOException e) {
            e.printStackTrace();

            throw new EsbSynException("写入dubbo汇总文件失败!");
        }finally{
            if (fos!=null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();

                    throw new EsbSynException("关闭dubbo汇总文件输入流失败!");
                }
            }
        }
    }
    
    /**
     * 查询F5配置中的service-code数量，并封装为List
     *
     * @return
     * @author fwj
     * @date 2015年12月6日12:28:14
     */
    public static List<Map<String, String>> formatServiceCode(String fileContent)  {
    
        
    
        List<Map<String, String>> list = new ArrayList<Map<String, String>>();
        try {
            //以下按固定格式写死截取字符串
            fileContent = fileContent.replaceAll(" ", "");
            String[] conS = null;
            if (fileContent.indexOf(nl_windows) > -1) {
                fileContent = fileContent.split("ltmdata-groupinternal/Common/service-code\\{" + nl_windows + "records")[1];
                fileContent = fileContent.split("\\}" + nl_windows + "typestring")[0];
                fileContent = fileContent.replaceAll("\\{", "").replaceAll("\\}" + nl_windows, "");
                conS = fileContent.split(nl_windows);
            } else {
                fileContent = fileContent.split("ltmdata-groupinternal/Common/service-code\\{" + nl_linux + "records")[1];
                fileContent = fileContent.split("\\}" + nl_linux + "typestring")[0];
                fileContent = fileContent.replaceAll("\\{", "").replaceAll("\\}" + nl_linux, "");
                conS = fileContent.split(nl_linux);
            }


            for (int i = 1; i < conS.length; i = i + 2) {//从第一个开始
                Map<String, String> map = new HashMap<String, String>();
                map.put("name", conS[i]);//service-code名称
                map.put("data", conS[i + 1].split("data")[1]);//其下的pool名称
                list.add(map);
            }
        } catch (ArrayIndexOutOfBoundsException e) {
            logger.error("截取字符出错！F5配置文件格式不正确！" + e.getMessage());
            e.printStackTrace();

        }
        return list;
    }


}
